/**
* This file is part of OntoCompoFramework
*
* Copyright (C) 2011 -  Christian Brel
*
* @author   Main    Christian Brel
**/
package ontocompo.ui.appmanagement;

import java.awt.Container;
import java.awt.event.MouseListener;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.EventListener;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Observable;
import java.util.Set;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.event.InternalFrameEvent;
import javax.swing.event.InternalFrameListener;

import ontocompo.ui.global.EventListenerArray;
import ontocompo.ui.global.Resources;
import ontocompo.ui.selection.SelectedComponent;
import ontocompo.ui.selection.Selector;
import ontocompo.ui.semantic.OntoCompoProperties;
import ontocompo.ui.semantic.SemanticInfo;

import org.objectweb.fractal.adl.ADLException;
import org.objectweb.fractal.api.Component;
import org.objectweb.fractal.api.NoSuchInterfaceException;
import org.objectweb.fractal.api.control.IllegalLifeCycleException;
import org.objectweb.fractal.julia.control.lifecycle.LifeCycleCoordinator;

import fr.inria.acacia.corese.api.IResult;
import fr.inria.acacia.corese.api.IResultValue;
import fr.inria.acacia.corese.api.IResults;
import fr.inria.acacia.corese.exceptions.EngineException;

public class Application extends Observable {

	private String name;
	private String componentAppName;
	private SemanticInfo semanticInfo;
	
	private JFrame appFrame;
	private JInternalFrame appInternalframe;
	
	private HashMap<java.awt.Component, ArrayList<EventListenerArray>> jcomponentsListeners;
	
	public Application(String name, String componentAppName, SemanticInfo semanticInfo) {
		this.name = name;
		this.componentAppName = componentAppName;
		this.semanticInfo = semanticInfo;
		
		this.appFrame = null;
		this.appInternalframe = null;
	}
	
	public String getName() {
		return this.name;
	}
	
	public String getComponentAppName() {
		return this.componentAppName;
	}
	
	public SemanticInfo getSemanticInfo() {
		return this.semanticInfo;
	}
	
	public JFrame getFrame() {
		if(this.appFrame == null) {
			this.loadApplication();
		}
		
		return this.appFrame;
	}
	
	public JInternalFrame getInternalFrame() {
		if(this.appInternalframe == null) {
			this.appInternalframe = new JInternalFrame(this.getName(), true, true, true, true);
			this.appInternalframe.setContentPane(this.getFrame().getContentPane());
			this.getFrame().setVisible(false);
			
			/*this.appInternalframe.addWindowListener(new java.awt.event.WindowAdapter() {
		        public void windowClosing(java.awt.event.WindowEvent evt) {
	                hide();
		        } 
			} );*/
			this.appInternalframe.addInternalFrameListener(new InternalFrameListener() {

				@Override
				public void internalFrameActivated(InternalFrameEvent arg0) {
					// TODO Auto-generated method stub
					internalFrameActivation();
				}

				@Override
				public void internalFrameClosed(InternalFrameEvent arg0) {
					// TODO Auto-generated method stub
					System.out.println("closed " + getName());
				}

				@Override
				public void internalFrameClosing(InternalFrameEvent arg0) {
					// TODO Auto-generated method stub
					System.out.println("closing " + getName());
					//TODO Traitement pour supprimer proprement l'application des application ouverte- destruction des composants fractal etc...
				}

				@Override
				public void internalFrameDeactivated(InternalFrameEvent arg0) {
					// TODO Auto-generated method stub
					
				}

				@Override
				public void internalFrameDeiconified(InternalFrameEvent arg0) {
					// TODO Auto-generated method stub
					
				}

				@Override
				public void internalFrameIconified(InternalFrameEvent arg0) {
					// TODO Auto-generated method stub
					
				}

				@Override
				public void internalFrameOpened(InternalFrameEvent arg0) {
					// TODO Auto-generated method stub
				}
				
			});
			
			//this.appInternalframe.setDefaultCloseOperation(JInternalFrame.DISPOSE_ON_CLOSE);
			
			this.appInternalframe.pack();
			this.appInternalframe.setVisible(true);
		}
		return this.appInternalframe;
	}
	
	private void internalFrameActivation() {
		this.setChanged();
		this.notifyObservers(this);
	}
	
	private void loadApplication() {
		try {
			Component appuicomponent = (Component) Resources.getFractalFactory().newComponent(this.getComponentAppName(), null);
		
		
			((LifeCycleCoordinator)appuicomponent.getFcInterface("lifecycle-controller")).startFc();
			
			ontocompo.api.UIJFrameService appJFrameService = (ontocompo.api.UIJFrameService)appuicomponent.getFcInterface("uijframeservice");
			appJFrameService.init();
			this.appFrame = appJFrameService.getJFrameItSelf();

			Resources.addResourceToCoreseEngine(Resources.ONTOAPPLICATIONS_ROOT_DIRECTORY_PATH + "/" + this.semanticInfo.getAppDirectory() + "/semantic/");
			
		} catch (ADLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalLifeCycleException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchInterfaceException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/*public void activateSelection(Selector s) {
		Container contentPane = this.appInternalframe.getContentPane();
		
		this.activateSelectionRecur(contentPane, s);
	}
	
	private void activateSelectionRecur(java.awt.Component c, Selector s) {
		if(isAnIdentifiedComponent(c)) {
			c.addMouseListener(s);
		}
		
		
		if (c instanceof Container)
		{
			Container cont = (Container) c;
			for(java.awt.Component subc : cont.getComponents())
			{
				activateSelectionRecur(subc, s);
			}
		}
	}*/
	
	public void activateSelection(Selector s) {
		/*Container contentPane = this.appInternalframe.getContentPane();
		
		this.activateSelectionRecur(contentPane, s);*/
		
		this.jcomponentsListeners = new HashMap<java.awt.Component, ArrayList<EventListenerArray>>();
		
		ArrayList<JComponent> availabledJComponents = this.getAvailabledJComponents();
		for(JComponent jc: availabledJComponents) {
			if(!Application.linkedToMouseListener(jc, s)) {
				this.delAndStockEventListeners(jc);
				jc.addMouseListener(s);
			}
		}
	}
	
	private void delAndStockEventListeners(java.awt.Component jc) {

		try {
			Method[] allMethodes = jc.getClass().getMethods();
			Set<Class<? extends EventListener>> collection = new HashSet<Class<? extends EventListener>>();
			for (Method m : allMethodes)
			{
				String name = m.getName();
				if (name.startsWith("add") && name.endsWith("Listener"))
				{
					if (m.getParameterTypes().length > 0)
					{
						Class paramType = m.getParameterTypes()[0];
						if (EventListener.class.isAssignableFrom(paramType))
						{
							collection.add(paramType);
						}
					}
				}
			}
			
			// collection.add(ActionListener.class);
			
			for(Class<? extends EventListener> c : collection)
			{
				//System.out.println(c.getSimpleName());
				EventListener[] listeners = jc.getListeners(c);
				if ((listeners == null) || (listeners.length == 0)) continue;
				
				EventListener l1 = listeners[0];
				
				String nameOfMethodToRemove = "remove"+c.getSimpleName();
				Method m;
					m = jc.getClass().getMethod(nameOfMethodToRemove, c);
				
				
				
				//Concentrator concentrator = new Concentrator (l1);
				for(EventListener l : listeners) {
					//System.out.println("debut " + l);
					m.invoke(jc, l) ;
					//System.out.println("fin " + l);
					//concentrator.addListener(l);
				}
				
				if(! this.jcomponentsListeners.containsKey(jc)) {
					this.jcomponentsListeners.put(jc, new ArrayList<EventListenerArray>());
				}
				ArrayList<EventListenerArray> ela = this.jcomponentsListeners.get(jc);
				ela.add(new EventListenerArray(c, listeners));
				
			}
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public void deactivateSelection(Selector s) {
		Container contentPane = this.appInternalframe.getContentPane();
		
		this.deactivateSelectionRecur(contentPane, s);
	}
	
	private void deactivateSelectionRecur(java.awt.Component c, Selector s) {
		if(isAnIdentifiedComponent(c) && Application.linkedToMouseListener(c, s)) {
			c.removeMouseListener(s);
			
			this.addingStockedEventListener(c);
			
		}
		
		if (c instanceof Container)
		{
			Container cont = (Container) c;
			for(java.awt.Component subc : cont.getComponents())
			{
				deactivateSelectionRecur(subc, s);
			}
		}
	}
	
	private void addingStockedEventListener(java.awt.Component jc) {
		try {
			if(this.jcomponentsListeners.containsKey(jc)) {
				ArrayList<EventListenerArray> eventListenerArrays = this.jcomponentsListeners.get(jc);
				
				for(EventListenerArray ela : eventListenerArrays) {
				
					EventListener[] listeners = ela.getEvents();
					
					
					
					String nameOfMethodToAdd = "add"+ela.getEventListenerClass().getSimpleName();
					Method m;
						
					m = jc.getClass().getMethod(nameOfMethodToAdd, ela.getEventListenerClass());
					
					//Concentrator concentrator = new Concentrator (l1);
					for(EventListener l : listeners) {
						//System.out.println("debut " + l);
						m.invoke(jc, l) ;
						//System.out.println("fin " + l);
						//concentrator.addListener(l);
					}
					
					this.jcomponentsListeners.remove(jc);
				}
			}
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public static boolean linkedToMouseListener(java.awt.Component c, Selector s) {
		MouseListener[] listeners = c.getMouseListeners();
		
		if(listeners.length > 0) {
			for(MouseListener ml: listeners) {
				if(ml.equals(s)) {
					return true;
				}
			}
		}
		
		return false;
	}
	
	public Boolean isAnIdentifiedComponent(java.awt.Component c) {
		String cid = this.getComponentUid(c);
		if(cid != null) {
			if(isSemanticUiEntity(cid)) {
				return true;
			}
		}
		
		return false;
	}
	
	public String getComponentUid(java.awt.Component c) {
		
		if(ontocompo.api.OntoCompoIntrospection.class.isAssignableFrom(c.getClass())) {
			ontocompo.api.OntoCompoIntrospection oci = (ontocompo.api.OntoCompoIntrospection) c;
			return oci.getUid();
		}
		
		return null;
	}
	
	private Boolean isSemanticUiEntity(String componentUid) {
		try {
			String getLinkedUiEntities = "SELECT * WHERE { " +
					"GRAPH <" + this.semanticInfo.getGraphName() + "> {" +
						"?uientity rdf:type <" + OntoCompoProperties.UIONTO + "#" + OntoCompoProperties.UIONTO_UIENTITY_CLASS + "> ." +
						"?uientity <" + OntoCompoProperties.ONTOCOMPO + "#" + OntoCompoProperties.ONTOCOMPO_LINKEDWITHFRACTALCOMPONENT_PROPERTY + "> '" + componentUid + "' " +
					"}" +
				"}";
//			System.err.println("Activate : " + getLinkedUiEntities);
			IResults resLinkedUiEntities = Resources.getCoreseEngine().SPARQLQuery(getLinkedUiEntities);
			
			if(resLinkedUiEntities.size() > 0) {
				return true;
			}
			
		} catch (EngineException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
		
		return false;
	}
	
	private Boolean isLinkedToTask(String componentUid) {
		try {
			String getLinkedTasks = "SELECT * WHERE { " +
					"GRAPH <" + this.semanticInfo.getGraphName() + "> {" +
						"?t rdf:type <" + OntoCompoProperties.TASKONTO + "#" + OntoCompoProperties.TASKONTO_TASK_CLASS + "> ." +
						"?t <" + OntoCompoProperties.ONTOCOMPO + "#" + OntoCompoProperties.ONTOCOMPO_LINKEDWITH_PROPERTY + "> ?uientity ." +
						"?uientity <" + OntoCompoProperties.ONTOCOMPO + "#" + OntoCompoProperties.ONTOCOMPO_LINKEDWITHFRACTALCOMPONENT_PROPERTY + "> '" + componentUid + "' " +
					"}" +
				"}";
//			System.out.println(getLinkedTasks);
			
			IResults resLinkedTasks = Resources.getCoreseEngine().SPARQLQuery(getLinkedTasks);
			
			if(resLinkedTasks.size() > 0) {
				return true;
			}
			
			/*for(Enumeration<IResult> enGetContainers = resGetContainers.getResults(); enGetContainers.hasMoreElements();) {
				IResult rGetContainers = enGetContainers.nextElement();
				
				IResultValue[] valuesGetContainers = rGetContainers.getResultValues("?s");
				
	  			
				String containerUri = valuesGetContainers[0].getStringValue();
			}
			
			return true;*/
		} catch (EngineException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
		
		return false;
	}
	
	private IResults getTasksLinkedToComponent(JComponent component) {
		if(this.isAnIdentifiedComponent(component)) {
			String componentUid = this.getComponentUid(component);
			try {
				String getLinkedTasks = "SELECT * WHERE { " +
						"GRAPH <" + this.semanticInfo.getGraphName() + "> {" +
							"?t rdf:type <" + OntoCompoProperties.TASKONTO + "#" + OntoCompoProperties.TASKONTO_TASK_CLASS + "> ." +
							"?t <" + OntoCompoProperties.ONTOCOMPO + "#" + OntoCompoProperties.ONTOCOMPO_LINKEDWITH_PROPERTY + "> ?uientity ." +
							"?uientity <" + OntoCompoProperties.ONTOCOMPO + "#" + OntoCompoProperties.ONTOCOMPO_LINKEDWITHFRACTALCOMPONENT_PROPERTY + "> '" + componentUid + "' " +
						"}" +
					"}";
//				System.out.println(getLinkedTasks);
				
				IResults resLinkedTasks = Resources.getCoreseEngine().SPARQLQuery(getLinkedTasks);
				
				return resLinkedTasks;
				/*for(Enumeration<IResult> enGetContainers = resGetContainers.getResults(); enGetContainers.hasMoreElements();) {
					IResult rGetContainers = enGetContainers.nextElement();
					
					IResultValue[] valuesGetContainers = rGetContainers.getResultValues("?s");
					
		  			
					String containerUri = valuesGetContainers[0].getStringValue();
				}
				
				return true;*/
			} catch (EngineException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return null;
			}
		}
		
		return null;
	}
	
	private IResults getFunctionalitiesLinkedToComponent(JComponent component) {
		if(this.isAnIdentifiedComponent(component)) {
			String componentUid = this.getComponentUid(component);
			try {
				String getLinkedFunctionalities = "SELECT * WHERE { " +
						"GRAPH <" + this.semanticInfo.getGraphName() + "> {" +
							"?t rdf:type <" + OntoCompoProperties.TASKONTO + "#" + OntoCompoProperties.TASKONTO_TASK_CLASS + "> ." +
							"?t <" + OntoCompoProperties.ONTOCOMPO + "#" + OntoCompoProperties.ONTOCOMPO_LINKEDWITH_PROPERTY + "> ?uientity ." +
							"?uientity <" + OntoCompoProperties.ONTOCOMPO + "#" + OntoCompoProperties.ONTOCOMPO_LINKEDWITHFRACTALCOMPONENT_PROPERTY + "> '" + componentUid + "' ." +
							"?t <" + OntoCompoProperties.ONTOCOMPO + "#" + OntoCompoProperties.ONTOCOMPO_LINKEDWITH_PROPERTY + "> ?f ." +
							"?f rdf:type <" + OntoCompoProperties.FUNCTONTO + "#" + OntoCompoProperties.FUNCTONTO_FUNCT_CLASS + "> " +
						"}" +
					"}";
//				System.out.println(getLinkedFunctionalities);
				
				IResults resLinkedFunctionalities = Resources.getCoreseEngine().SPARQLQuery(getLinkedFunctionalities);
				
				return resLinkedFunctionalities;

			} catch (EngineException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return null;
			}
		}
		
		return null;
	}
	
	private String getParentTask(String taskUri) {
		try {
			String getParentTask = "SELECT * WHERE { " +
					"GRAPH <" + this.semanticInfo.getGraphName() + "> {" +
						"<" + taskUri + "> rdf:type <" + OntoCompoProperties.TASKONTO + "#" + OntoCompoProperties.TASKONTO_TASK_CLASS + "> ." +
						"?parentTask rdf:type <" + OntoCompoProperties.TASKONTO + "#" + OntoCompoProperties.TASKONTO_TASK_CLASS + "> ." +
						"<" + taskUri + "> <" + OntoCompoProperties.TASKONTO + "#" + OntoCompoProperties.TASKONTO_HASPARENTTASK_PROPERTY + "> ?parentTask " +
					"}" +
				"}";
			System.err.println(getParentTask);
			
			IResults resParentTask = Resources.getCoreseEngine().SPARQLQuery(getParentTask);

			for(Enumeration<IResult> enParentTask = resParentTask.getResults(); enParentTask.hasMoreElements();) {
				IResult rParentTask = enParentTask.nextElement();
				
				IResultValue[] valuesParentTask = rParentTask.getResultValues("?parentTask");
				
				String parentTaskUri = valuesParentTask[0].getStringValue();
				
				return parentTaskUri;
			}
			
		} catch (EngineException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
		
		return null;
	}
	
	private ArrayList<JComponent> getComponentsLinkedToTask(String taskUri) {
		ArrayList<JComponent> components = new ArrayList<JComponent>();
		try {
			String getLinkedComponents = "SELECT * WHERE { " +
					"GRAPH <" + this.semanticInfo.getGraphName() + "> {" +
						"<" + taskUri + "> rdf:type <" + OntoCompoProperties.TASKONTO + "#" + OntoCompoProperties.TASKONTO_TASK_CLASS + "> ." +
						"<" + taskUri + "> <" + OntoCompoProperties.ONTOCOMPO + "#" + OntoCompoProperties.ONTOCOMPO_LINKEDWITH_PROPERTY + "> ?uientity ." +
						"?uientity <" + OntoCompoProperties.ONTOCOMPO + "#" + OntoCompoProperties.ONTOCOMPO_LINKEDWITHFRACTALCOMPONENT_PROPERTY + "> ?c " +
					"}" +
				"}";
//			System.out.println(getLinkedComponents);
			
			IResults resLinkedTasks = Resources.getCoreseEngine().SPARQLQuery(getLinkedComponents);

			for(Enumeration<IResult> enLinkedTasks = resLinkedTasks.getResults(); enLinkedTasks.hasMoreElements();) {
				IResult rLinkedTasks = enLinkedTasks.nextElement();
				
				IResultValue[] valuesLinkedTasks = rLinkedTasks.getResultValues("?c");
				
	  			
				String containerUri = valuesLinkedTasks[0].getStringValue();
				
				JComponent component = this.getJComponentFromComponentUid(containerUri);
				
				if(component != null) {
					components.add(component);
				}
			}
			
			return components;
			
		} catch (EngineException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}
	
	private ArrayList<JComponent> getComponentsLinkedToFunctionality(String functionalityUri) {
		ArrayList<JComponent> components = new ArrayList<JComponent>();
		try {
			String getLinkedComponents = "SELECT * WHERE { " +
					"GRAPH <" + this.semanticInfo.getGraphName() + "> {" +
						"<" + functionalityUri + "> rdf:type <" + OntoCompoProperties.FUNCTONTO + "#" + OntoCompoProperties.FUNCTONTO_FUNCT_CLASS + "> ." +
						"?t <" + OntoCompoProperties.ONTOCOMPO + "#" + OntoCompoProperties.ONTOCOMPO_LINKEDWITH_PROPERTY + "> <" + functionalityUri + "> ." +
						"?t <" + OntoCompoProperties.ONTOCOMPO + "#" + OntoCompoProperties.ONTOCOMPO_LINKEDWITH_PROPERTY + "> ?uientity ." +
						"?uientity rdf:type <" + OntoCompoProperties.UIONTO + "#" + OntoCompoProperties.UIONTO_UIENTITY_CLASS + "> ." +
						"?uientity <" + OntoCompoProperties.ONTOCOMPO + "#" + OntoCompoProperties.ONTOCOMPO_LINKEDWITHFRACTALCOMPONENT_PROPERTY + "> ?c " +
					"}" +
				"}";
//			System.out.println(getLinkedComponents);
			
			IResults resLinkedFunctionalities = Resources.getCoreseEngine().SPARQLQuery(getLinkedComponents);

			for(Enumeration<IResult> enLinkedFunctionalities = resLinkedFunctionalities.getResults(); enLinkedFunctionalities.hasMoreElements();) {
				IResult rLinkedFunctionalities = enLinkedFunctionalities.nextElement();
				
				IResultValue[] valuesLinkedFunctionalities = rLinkedFunctionalities.getResultValues("?c");
				
	  			
				String containerUri = valuesLinkedFunctionalities[0].getStringValue();
				
				JComponent component = this.getJComponentFromComponentUid(containerUri);
				
				if(component != null) {
					components.add(component);
				}
			}
			
			return components;
			
		} catch (EngineException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}
	
	public JComponent getJComponentFromComponentUid(String componentUid) {
		ArrayList<JComponent> availabledComponents = this.getAvailabledJComponents();
		for(JComponent c: availabledComponents) {
			String cUid = this.getComponentUid(c);
			if(cUid != null && cUid.equals(componentUid)){
				return c;
			}
		}
		return null;
	}
	
	public ArrayList<JComponent> getAvailabledJComponents() {
		Container contentPane = this.appInternalframe.getContentPane();
		
		ArrayList<JComponent> availabledJComponents = new ArrayList<JComponent>();
		this.getAvailabledJComponentsRecur(contentPane, availabledJComponents);
		return availabledJComponents;
	}
	
	private ArrayList<JComponent> getAvailabledJComponentsRecur(java.awt.Component c, ArrayList<JComponent> availabledJComponents) {
		if(isAnIdentifiedComponent(c)) {
			availabledJComponents.add((JComponent) c);
		}
		
		
		if (c instanceof Container)
		{
			Container cont = (Container) c;
			for(java.awt.Component subc : cont.getComponents())
			{
				getAvailabledJComponentsRecur(subc, availabledJComponents);
			}
		}
		
		return availabledJComponents;
	}
	
	public String toString() {
		return this.getName();
	}

	public boolean containsJComponent(JComponent component) {
		for(JComponent jc: this.getAvailabledJComponents()) {
			if(jc.equals(component)) {
				return true;
			}
		}
		
		return false;
	}

	public JComponent getParentOfComponent(JComponent component) {
		Container parent = null;
		Container current = component;
		
		while(parent == null && current.getParent() != null) {
			if(this.isAnIdentifiedComponent(current.getParent())) {
				parent = current.getParent();
			} else {
				current = current.getParent();
			}
		}
		
		return (JComponent) parent;
	}

	public ArrayList<JComponent> getTaskContentFromSelectedComponent(JComponent component) {
		ArrayList<JComponent> components = new ArrayList<JComponent>();
		IResults tasksList = this.getTasksLinkedToComponent(component);
		
		for(Enumeration<IResult> tasks = tasksList.getResults(); tasks.hasMoreElements();) {
			IResult task = tasks.nextElement();
			
			IResultValue[] taskResult = task.getResultValues("?t");
			
  			
			String taskUri = taskResult[0].getStringValue();
			
			ArrayList<JComponent> taskComponents = this.getComponentsLinkedToTask(taskUri);
			
			components.addAll(taskComponents);
		}
		
		return components;
	}
	
	public ArrayList<JComponent> getParentTaskContentFromSelectedComponent(JComponent component) {
		ArrayList<JComponent> components = new ArrayList<JComponent>();
		IResults tasksList = this.getTasksLinkedToComponent(component);
		
		for(Enumeration<IResult> tasks = tasksList.getResults(); tasks.hasMoreElements();) {
			IResult task = tasks.nextElement();
			
			IResultValue[] taskResult = task.getResultValues("?t");
			
  			
			String taskUri = taskResult[0].getStringValue();
			
			String parentTaskUri = this.getParentTask(taskUri);
			//TODO A Tester avec l'interface Corese
			System.err.println(taskUri + " et parent:  " + parentTaskUri);
			if(parentTaskUri != null) {
				ArrayList<JComponent> taskComponents = this.getComponentsLinkedToTask(parentTaskUri);
			
				components.addAll(taskComponents);
			}
		}
		
		return components;
	}
	
	public ArrayList<JComponent> getFunctionalityContentFromSelectedComponent(JComponent component) {
		ArrayList<JComponent> components = new ArrayList<JComponent>();
		IResults functionalitiesList = this.getFunctionalitiesLinkedToComponent(component);
		
		for(Enumeration<IResult> functionalities = functionalitiesList.getResults(); functionalities.hasMoreElements();) {
			IResult functionality = functionalities.nextElement();
			
			IResultValue[] functionalityResult = functionality.getResultValues("?f");
			
  			
			String functionalityUri = functionalityResult[0].getStringValue();
			
			ArrayList<JComponent> functionalityComponents = this.getComponentsLinkedToFunctionality(functionalityUri);
			
			components.addAll(functionalityComponents);
		}
		
		return components;
	}
	
	public ArrayList<JComponent> getLayoutContentFromSelectedComponent(JComponent component, String direction) {		
		if(this.isAnIdentifiedComponent(component)) {
			String componentUid = this.getComponentUid(component);
			
			String directionOntoProperty = "";
			
			if(direction == "topleft") {
				directionOntoProperty = OntoCompoProperties.LAYONTO_ABOVELEFT_PROPERTY;
			} else if(direction == "top") {
				directionOntoProperty = OntoCompoProperties.LAYONTO_ABOVE_PROPERTY;
			} else if(direction == "topright") {
				directionOntoProperty = OntoCompoProperties.LAYONTO_ABOVERIGHT_PROPERTY;
			} else if(direction == "left") {
				directionOntoProperty = OntoCompoProperties.LAYONTO_ONLEFT_PROPERTY;
			} else if(direction == "right") {
				directionOntoProperty = OntoCompoProperties.LAYONTO_ONRIGHT_PROPERTY;
			} else if(direction == "bottomleft") {
				directionOntoProperty = OntoCompoProperties.LAYONTO_BELOWLEFT_PROPERTY;
			} else if(direction == "bottom") {
				directionOntoProperty = OntoCompoProperties.LAYONTO_BELOW_PROPERTY;
			} else if(direction == "bottomright") {
				directionOntoProperty = OntoCompoProperties.LAYONTO_BELOWRIGHT_PROPERTY;
			}
			
			ArrayList<JComponent> components = new ArrayList<JComponent>();
			try {
				String getLinkedComponents = "SELECT * WHERE { " +
						"GRAPH <" + this.semanticInfo.getGraphName() + "> {" +
							"?uientity <" + OntoCompoProperties.ONTOCOMPO + "#" + OntoCompoProperties.ONTOCOMPO_LINKEDWITHFRACTALCOMPONENT_PROPERTY + "> '" + componentUid + "' . " +
							"?uientity2 <" + OntoCompoProperties.LAYONTO + "#" + directionOntoProperty + "> ?uientity . " +
							"?uientity2 <" + OntoCompoProperties.ONTOCOMPO + "#" + OntoCompoProperties.ONTOCOMPO_LINKEDWITHFRACTALCOMPONENT_PROPERTY + "> ?componentID" +
						"}" +
					"}";
				System.out.println(getLinkedComponents);
				
				IResults resLayoutComponents = Resources.getCoreseEngine().SPARQLQuery(getLinkedComponents);
	
				for(Enumeration<IResult> enLayoutComponents = resLayoutComponents.getResults(); enLayoutComponents.hasMoreElements();) {
					IResult rLayoutComponents = enLayoutComponents.nextElement();
					
					IResultValue[] valuesLayoutComponents = rLayoutComponents.getResultValues("?componentID");
					
		  			
					String containerUri = valuesLayoutComponents[0].getStringValue();
					
					JComponent componentToAdd = this.getJComponentFromComponentUid(containerUri);
					
					if(componentToAdd != null) {
						components.add(componentToAdd);
					}
				}
				
				return components;
				
			} catch (EngineException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return null;
			}
		}
		return null;
	}
	
	public JComponent extractComponent(JComponent toExtract, Selector s) {
		this.deactivateSelectionRecur(toExtract, s);
		
		return this.extractComponent(toExtract);
		
//		return toExtract;
	}
	
	public JComponent extractComponent(JComponent toExtract) {
		Container parent = toExtract.getParent();
		parent.remove(toExtract);
		
		this.addingStockedEventListener(toExtract);
		
		return toExtract;
	}
	
	public JComponent getValidParentOfComponent(JComponent component) {		
		JComponent currentComponent = component;
		JComponent parent = null;
		
		while(parent == null && currentComponent.getParent() != null) {
			if(currentComponent.getParent().getClass().isAssignableFrom(JComponent.class)) {
				parent = (JComponent) currentComponent.getParent();
			} else {
				parent = null;
				break;
			}
			
			if(!this.isAnIdentifiedComponent(parent)) {
				currentComponent = parent;
				parent = null;
			}
		}
		
		return parent;
		
	}
	
	public ArrayList<JComponent> getValidSonsOfComponent(JComponent parentComponent) {
		ArrayList<JComponent> validSons = new ArrayList<JComponent>();
		
		java.awt.Component[] sons = parentComponent.getComponents();
		
		for(java.awt.Component son: sons) {
			if(this.isAnIdentifiedComponent(son)) {
				validSons.add((JComponent) son);
			}
		}
		
		return validSons;
	}
}
